<?php
/**
 *                    _ooOoo_
 *                   o8888888o
 *                   88" . "88
 *                   (| -_- |)
 *                    O\ = /O
 *                ____/`---'\____
 *              .   ' \\| |// `.
 *               / \\||| : |||// \
 *             / _||||| -:- |||||- \
 *               | | \\\ - /// | |
 *             | \_| ''\---/'' | |
 *              \ .-\__ `-` ___/-. /
 *           ___`. .' /--.--\ `. . __
 *        ."" '< `.___\_<|>_/___.' >'"".
 *       | | : `- \`.;`\ _ /`;.`/ - ` : | |
 *         \ \ `-. \_ __\ /__ _/ .-` / /
 * ======`-.____`-.___\_____/___.-`____.-'======
 *                    `=---='
 *
 * .............................................
 *          佛祖保佑             永无BUG
 */

namespace App\Repositories;


use App\Exceptions\ExpressException;
use App\Interfaces\Express;
use App\OrderPay;
use App\SenderConfig;
use GuzzleHttp\Client;
use GuzzleHttp\Pool;
use GuzzleHttp\Promise\Promise;
use function GuzzleHttp\Promise\unwrap;
use GuzzleHttp\Psr7\Request;
use Illuminate\Support\Facades\Log;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Exception\RequestException;

class ExpressRepository implements Express
{
    protected $client;
    protected $url ;//请求url
    protected $partnerid;
    protected $password;
    protected $version ;
    protected $query_url ;

    public function __construct(Client $client)
    {
        $this->client = $client;
        $this->url=config('express.express_url');
        $this->partnerid=config('express.express_partnerid');
        $this->password=config('express.express_password');
        $this->version=config('express.express_version');
        $this->query_url=config('express.express_query_url');
        //dd($this->query_url);
    }

    public function expressQuery($mailno)
    {
        $response = $this->client->request('get', $this->query_url, [
            'query' => [
                'partnerid' => $this->partnerid,
                'mailno' => 1200000000001,
                'charset' => 'utf8'
            ]
        ]);
        $body = $response->getBody();
        return json_decode($body->getContents(), true);

    }

    public function expressQueryAsync($mail_no)
    {
        $client = $this->client;
        $promise = $client->requestAsync('get', $this->query_url, [
            'query' => [
                'partnerid' => $this->partnerid,
                'mailno' => $mail_no,
                'charset' => 'utf8'
            ]
        ]);
        $promise->then(
            function (ResponseInterface $res) use ($mail_no) {
                $body = $res->getBody();
                $expressInfo = json_decode($body->getContents(), true);
                Log::info('物流信息',$expressInfo);
                $order = OrderPay::where('mail_no', $mail_no)->first();
                if ($order) {
                    if (isset($expressInfo['status']) && $expressInfo['status'] == 'signed') {
                        $order->ship_status = OrderPay::SHIP_STATUS_RECEIVED;
                    }
                    $order->ship_data=$expressInfo;
                    $ture = $order->save();
                }
            },
            function (ExpressException $e) {
                // echo $e->getMessage() . "\n";
                Log::error('异步请求error', $e->getMessage());
            }
        );
        $promise->wait();


    }

    protected function updateExpress($express_no, $expressInfo)
    {
        $express = json_decode($expressInfo, true);
        $order = OrderPay::where('mail_no', $express_no)->first();
        $order->ship_data = $express;
        if (isset($expressInfo['status']) && $expressInfo['status'] == 'signed') {
            $order->ship_status = OrderPay::SHIP_STATUS_RECEIVED;
        }

        $order->save();

    }

    /*  public function expressQueryAsync($express_no)
      {
          $client=$this->client;
          $requests = function ($total) use($client) {
              $uri = self::QUERY_URL;
              for ($i = 0; $i < $total; $i++) {
                  yield function()use($client){
                   return    $client->requestAsync('get',self::QUERY_URL,[
                          'query' => [
                              'partnerid'=>'yunda',
                              'mailno'=>1200000000001,
                              'charset'=>'utf8'
                          ]
                      ]);
                  };
              }
          };

          $pool = new Pool($this->client, $requests(10), [
              'concurrency' => 5,
              'fulfilled' => function ($response, $index) {
                  $body = $response->getBody();
                  $result= json_decode($body->getContents(),true);
                  // this is delivered each successful response
                  Log::info('物流信息请求成功'.$index,$result);
              },
              'rejected' => function ($reason, $index) {
                  // this is delivered each failed request
                  Log::info('请求失败'.$index);
              },
          ]);
          $promise = $pool->promise();

  // Force the pool of requests to complete.
          $promise->wait();


      }*/

    public function updateOrderStatus()
    {
        // TODO: Implement updateOrderStatus() method.
    }

    protected function createExpressNo()
    {
        return ;
    }

    public function creatExpress(OrderPay $orderPay)
    {

        $order_serial_no = $this->createExpressNo();
        $senderConfig = SenderConfig::first();
        $goods = $orderPay->goods;
        $goodsArray = [];
        foreach ($goods as $k => $v) {
            $goodsArray[$k]['item']['name'] = $v->good_object['goods_name'];
            $goodsArray[$k]['item']['number'] = $v->buy_num;
        }
        $xmldata = [
            'order' => [
                'order_serial_no' => $orderPay->pay_sn,
                'khddh' => $orderPay->pay_sn,
                'nbckh' => '',

                'sender' => [
                    'name' => $senderConfig->name,
                    'company' => $senderConfig->company,
                    'city' => $senderConfig->city,
                    'address' => $senderConfig->address,
                    'postcode' => $senderConfig->postcode,
                    'mobile' => $senderConfig->mobile,
                    'branch' => '',
                ],
                'receiver' => [
                    'name' => $orderPay->address->consignee,
                    'company' => '',
                    'city' => $orderPay->address->province . ',' . $orderPay->address->city . ',' . $orderPay->address->country,
                    'address' => $orderPay->address->province . ',' . $orderPay->address->city . ',' . $orderPay->address->district . $orderPay->address->address,
                    'postcode' => '',
                    'mobile' => $orderPay->address->mobile,
                    'branch' => '',
                ],
                'weight' => ' ',
                'size' => ' ',
                'value' => $orderPay->total_money,
                'collection_value' => '',
                'special' => '',
                'items' => $goodsArray,
                'remark' => '',
                'cus_area1' => '',
                'cus_area2' => '',
                'callback_id' => '',
                'wave_no' => ''
            ],
        ];
       // dd($xmldata);
        $data = $this->httpRequest('data', $xmldata, 'interface_receive_order__mailno.php');
        if (isset($data->response->pdf_info)) {
            $pdfInfo = json_decode($data->response->pdf_info, true);
        } else {
            $pdfInfo = [];
        }


        $data = json_decode(json_encode($data), true)['response'];

        $data['pdf_info'] = $pdfInfo;
        return $data;

    }

    public function findExpress(array $order_serial_nos)
    {//查询运单状态
        if (empty($order_serial_nos)) {
            throw  new ExpressException('运单id不能为空');
        }

        $orderArray = [];
        foreach ($order_serial_nos as $k => $v) {
            $orderArray['order']['order_serial_no'] = $v;
            $orderArray['order']['mailno'] = '';
            $orderArray['order']['print_file'] = 0;
            $orderArray['order']['json_data'] = 1;
        }
        $xmldata = $orderArray;

        $this->httpRequest('transite_info', $xmldata, 'interface_order_info.php');
    }

    protected function httpRequest($request, array $xmldata, $uri)
    {
        $baseData = [
            'partnerid' => $this->partnerid,
            'request' => $request,
            'version' => $this->version,
        ];

        $baseData['xmldata'] = view('admin.orders.express',compact('xmldata'))->render();

        //base64 编码
        $baseData['xmldata'] = base64_encode($baseData['xmldata']);

        //签名
        $baseData['validation'] = $this->getValidate($baseData['xmldata']);

        $response = $this->client->request('post', $this->url . $uri, [
            'form_params' => $baseData
        ]);

        $body = $response->getBody();

        libxml_disable_entity_loader(true);

        $data = simplexml_load_string($body->getContents(), 'SimpleXMLElement', LIBXML_NOCDATA);

        return $data;
    }

    protected function arrayToXml($arr, $dom = null, $node = null, $root = 'orders', $cdata = false)
    {
        if (!$dom) {
            $dom = new \DOMDocument('1.0', 'utf-8');
        }
        if (!$node) {
            $node = $dom->createElement($root);
            $dom->appendChild($node);
        }
        foreach ($arr as $key => $value) {
            $child_node = $dom->createElement(is_string($key) ? $key : 'item');
            $node->appendChild($child_node);
            if (!is_array($value)) {
                if (!$cdata) {
                    $data = $dom->createTextNode($value);
                } else {
                    $data = $dom->createCDATASection($value);
                }
                $child_node->appendChild($data);
            } else {
                $this->arrayToXml($value, $dom, $child_node, $root, $cdata);
            }
        }
        return $dom->saveXML();
    }


    protected function getValidate($xmlData)
    {
        return md5($xmlData . $this->partnerid . $this->password);
    }

}